package com.heima.wemedia.scan.service.iml;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.common.utils.CollectionUtils;
import com.heima.aliyun.AliyunGreenTemplate;

import com.heima.model.article.dto.ArticleDto;
import com.heima.feign.ArticleFeignClient;
import com.heima.file.MinIOTemplate;

import com.heima.model.common.dtos.ResponseResult;
import com.heima.model.wemedia.entity.WmChannel;
import com.heima.model.wemedia.entity.WmNews;
import com.heima.model.wemedia.entity.WmUser;
import com.heima.utils.common.SensitiveWordUtil;
import com.heima.wemedia.scan.dao.WmChannelDao;
import com.heima.wemedia.scan.dao.WmNewsDao;
import com.heima.wemedia.scan.dao.WmUserDao;
import com.heima.wemedia.scan.service.WmNewsAutoScanService;
import io.micrometer.core.instrument.util.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class WmNewsAutoScanServiceImpl implements WmNewsAutoScanService {
    @Resource
    private WmNewsDao wmNewsDao;
    @Resource
    private WmChannelDao wmChannelDao;
    @Resource
    private WmUserDao wmUserDao;

    @Resource
    private MinIOTemplate minIOTemplate;

    @Resource
    private AliyunGreenTemplate aliyunGreenTemplate;
    @Resource
    private ArticleFeignClient articleFeignClient;

    @Override
    public void autoScanNews(Long newsId) {
        WmNews wmNews = wmNewsDao.queryById(newsId);
        //1. 查询文章详情, 判断文章是否存在
        if (wmNews == null) {
            throw new RuntimeException("文章数据不存在");
        }
        //状态判断 ---- 不是待审核, 直接返回
        if (wmNews.getStatus() != 1) {
            return;
        }
        //2. 抽取文章文本内容和图片数据
        Map<String, Object> textAndImages = extractTextAndImages(wmNews);
        //3. 内容审核
        //3.1 文本审核
        String text1 = (String) textAndImages.get("text");
        boolean sitivescan = handleSensitiveScan(wmNews, text1);
        // 如果返回不成功就停止
        if (!sitivescan) {
            return;
        }
        boolean textScan = handleTextScan(wmNews, text1);
        //如果返回不成功就停止
        if (!textScan) {
            return;
        }
        //3.2 图片审核
        List<String> images = (List<String>) textAndImages.get("images");
        boolean imagesScan = handleImagesScan(wmNews, images);
        //如果返回不成功就停止
        if (!imagesScan) {
            return;
        }
        //4. 审核通过, 修改文章状态
        if (wmNews.getPublishTime().getTime() > System.currentTimeMillis()) {
            updateStatus(wmNews, (short) 8, "审核通过");
            return;
        }
        //4.2 如果已经到了用户设置的发布时间, 需要修改文章状态为9 , 并且发布文章
        saveArticle(wmNews);
    }

    /**
     * 审核通过发布文章
     *
     * @param wmNews
     */
    public ResponseResult saveArticle(WmNews wmNews) {
        //1. 封装参数
        ArticleDto articleDto = new ArticleDto();
        BeanUtils.copyProperties(wmNews, articleDto);
        //处理数据  id  authorId authorName  channelName  layout
        articleDto.setNewsId(wmNews.getId());
        articleDto.setAuthorId(wmNews.getUserId());
        WmUser wmUser = wmUserDao.queryById(Integer.parseInt(wmNews.getUserId() + ""));
        if (wmUser != null) {
            articleDto.setAuthorName(wmUser.getNickname());
        }
        WmChannel wmChannel = wmChannelDao.queryById(wmNews.getChannelId());
        if (wmChannel != null) {
            articleDto.setChannelName(wmChannel.getName());
        }
        articleDto.setLayout(wmNews.getType());
        //2. 调用远程feign接口发布文章
        ResponseResult result = articleFeignClient.save(articleDto);

        if (result.getCode() == 200) {
            updateStatus(wmNews, (short) 9, "审核通过 , 已发布");
        }
        return ResponseResult.okResult(result);
    }

    /**
     * 敏感词审核
     *
     * @param wmNews
     * @param text
     * @return
     */
    private boolean handleSensitiveScan(WmNews wmNews, String text) {
        //1. 判断审核文本是否为空
        if (StringUtils.isBlank(text)) {
            return true;
        }
        //3. 进行敏感词匹配
        Map<String, Integer> result = SensitiveWordUtil.matchWords(text);
        if (result.size() > 0) {
            updateStatus(wmNews, (short) 2, "我简约钱过滤，文本或图片内容中包含敏感词");
            return false;
        }

        return true;
    }

    /**
     * 图片审核
     *
     * @param wmNews
     * @param images1
     * @return
     */
    private boolean handleImagesScan(WmNews wmNews, List<String> images1) {
        //1. 判断图片是否存在
        if (CollectionUtils.isEmpty(images1)) {
            //没有图片直接看文本
            return true;
        }
        List<String> images = images1.stream().distinct().collect(Collectors.toList());//去重
        //2. 下载图片字节
        /*List<byte[]> collect = images.stream()
                .map(image -> minIOTemplate.downLoadFile(image))
                .collect(Collectors.toList());*/
        List<byte[]> list = new ArrayList<>();
        for (String image : images) {
            byte[] bytes = minIOTemplate.downLoadFile(image);
            list.add(bytes);
        }
        //3. 调用阿里云审核图片  pass block review
        Map<String, String> result = aliyunGreenTemplate.greenImageScan(list);
        //审核失败, 图片中包含违规信息
        if ("block".equals(result.get("suggestion"))) {
            //修改状态
            updateStatus(wmNews, (short) 2, "图片内容中包含违规信息");
            return false;
        }
        //需要进行人工审核
        if ("review".equals(result.get("suggestion"))) {
            //修改状态
            updateStatus(wmNews, (short) 3, "图片内容中包含不确定信息");
            return false;
        }
        return true;
    }

    /**
     * 文本审核
     *
     * @param wmNews
     * @param text1
     * @return
     */
    private boolean handleTextScan(WmNews wmNews, String text1) {
        //1. 判断文本是否存在
        if (text1 == null) {
            return false;
        }
        //使用阿里云进行文本审核  pass    review
        Map<String, String> result = aliyunGreenTemplate.greenTextScan(text1);
        //审核失败, 内容中包含违规信息
        if ("block".equals(result.get("suggestion"))) {
            //修改状态
            updateStatus(wmNews, (short) 2, "文章内容中包含违规信息");
            return false;
        }
        //需要进行人工审核
        if ("review".equals(result.get("suggestion"))) {
            //修改状态
            updateStatus(wmNews, (short) 3, "文章内容中包含不确定信息");
            return false;
        }

        return true;
    }

    //抽取出来修改状态
    private void updateStatus(WmNews wmNews, short i, String img) {
        wmNews.setStatus((int) i);
        wmNews.setReason(img);
        wmNewsDao.update(wmNews);
    }

    /**
     * 抽取文本和图片
     *
     * @param wmNews
     * @return
     */
    private Map<String, Object> extractTextAndImages(WmNews wmNews) {
        //1. 抽取文章内容中的图片和文本
        String content = wmNews.getContent();
        List<Map> maps = JSON.parseArray(content, Map.class);
        //创建容器封装数据
        StringBuilder sb = new StringBuilder(); //文本
        List<String> images = new ArrayList<>();
        //分别封装数据
        for (Map map : maps) {
            //图片数据
            if ("image".equals(map.get("type"))) {
                images.add((String) map.get("value"));
            }
            //文本数据
            if ("text".equals(map.get("type"))) {
                sb.append(map.get("value").toString());
            }
        }
        //2. 抽取标题文本和封面图片
        //封装标题
        String title = wmNews.getTitle();
        sb.append(title);
        //封装封面图片
        if (StringUtils.isNotBlank(wmNews.getImages())) {
            String[] split = wmNews.getImages().split(",");
            images.addAll(Arrays.asList(split));
        }
        //把文本和图片存入Map集合里返回
        Map<String, Object> result = new HashMap<>();
        result.put("text", sb.toString());
        result.put("images", images);

        return result;
    }
}
